package com.mxw.rulesengine.service;

import cn.hutool.core.collection.CollUtil;
import com.mxw.commons.errorcode.GlobalErrorCode;
import com.mxw.commons.exception.CustomException;
import com.mxw.rulesengine.errorcode.RulesEngineErrorCode;
import com.mxw.rulesengine.mapper.domain.Rule;
import com.mxw.rulesengine.utils.RulesEngineUtil;
import lombok.extern.slf4j.Slf4j;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.internal.utils.KieHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/** @Description TODO @Author RingKo @Date 2022/8/3 18:50 @Version 1.0 */
@Slf4j
@Service
public class RuleEngineService {
  @Autowired private KieHelper kieHelper;
  @Autowired private RuleService ruleService;

  @PostConstruct
  public void init() {
    reloadAll();
  }

  /**
   * @Description: 更新所有规则
   */
  public void reloadAll() {
    List<Rule> rules = ruleService.list();
    if (!CollUtil.isEmpty(rules)) {
      for (Rule rule : rules) {
        String content = rule.getContent();
        kieHelper.addContent(content, rule.getId() + ".drl");
      }
    }
    verifyRules();
  }

  /**
   * @Description: 通过id更新规则
   */
  public void reloadById(Integer id) {
    Rule rule =
        Optional.ofNullable(ruleService.getById(id))
            .orElseThrow(() -> new CustomException(GlobalErrorCode.DATA_NOT_FOUND, "未查询到规则"));
    String content = rule.getContent();
    kieHelper.addContent(content, rule.getId() + ".drl");
    verifyRules();
  }

  /**
   * @Description: 校验规则是否异常，并刷新容器
   */
  private void verifyRules() {
    Results results = kieHelper.verify();
    List<Message> messages =
        results.getMessages().stream()
            .filter(item -> Message.Level.ERROR.equals(item.getLevel()))
            .collect(Collectors.toList());
    if (CollUtil.isNotEmpty(messages)) {
      messages.forEach(item -> log.error(item.toString()));
      throw new CustomException(RulesEngineErrorCode.FAILED_TO_LOAD_RULES);
    }
    // 重置容器
    RulesEngineUtil.setKieContainer(kieHelper.getKieContainer());
  }
}
